#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include "windows.h"
#include "..\base_code\base_all.h"
#include "..\base_code\base_math.h"
#include "..\base_code\base_str.h"

extern rand_func_t rand_func_list[];

/* THIS WILL LOOP AND TEST ALL THE RANDOM FUNCTIONS
		The bitbucket test is a 2^32 bit array which is flagged true if it is hit. This is a quick way to see if
	the function(s) duplicate their numbers in an unusual way. This test is how cong was exposed as a non-repeating
	lcs. Speed is also measured in a subsequent loop.
	
	Kiss: Good, not quick - easy to initialize (5 numbers)
	MWC256: Good, quick - needs a 256 array initializer
	XORShift: Good, fast - easy to initialize (5 numbers)
	MT: Good, slowest - good as a baseline against other tests
	Cong: Not good in diehard - non repeating! which is interesting and possibly very useful (but not truly random) - very fast - easy to intialize
	LFSR113 and TAUS88: Good, slow - good for comparisons since they apparently use different algorithms
*/
int main () {
    unsigned i,j;
    unsigned randval;
    unsigned loopcount=100000000;
    unsigned c0, c1;
    unsigned long long total;
    rand_func_t *randfunc;
   	bitarray_t *bitarray;
   	unsigned dupes;


    // INITIALIZE ALL RANDOM FUNCTIONS
    Random_KISS_Init(3395943660);
    Random_MWC256_Init();
    Random_XORSHIFT_Init();
    Random_Cong_Init(3395943660);
    Random_MT_Init(3395943660);

    // LOOP THE RAND FUNCTIONS    
	bitarray = BitArray_Init(4294967296); // a bucket for every value 2^32

    for (randfunc = rand_func_list; randfunc->rand_func; randfunc++) {

		// BIT BUCKET TEST TO CHECK FOR DUPES
		BitArray_Wipe( bitarray );
		dupes=0;
		//for (i = 0; i < items*155; i++) { // populate the bins using each random function
		for (i = 0; i < loopcount; i++) { // populate the bins using each random function
			randval = randfunc->rand_func();
			if (BitArray_Value_Get(bitarray, randval)) {
				//__asm int 3;
				dupes++; // this is total number added to bins after bin is populated - or total cumulative dupes
			} else
				BitArray_Value_Set(bitarray, randval, true);
		}
		printf ( "%s has %s dupes \n", randfunc->fname, Str_Val(&dupes, true, str_val_intu ).str );
		
		c0 = GetTickCount();
		total=0;
		for (j = 0; j < loopcount; j++) {
			randval = randfunc->rand_func();
			total +=randval;
		}
		c1 = GetTickCount();
		printf ( "%s time: %8.4fs %s \n", randfunc->fname, (c1 - c0) / (double)1000, Str_Val( &total, true, str_val_int64u ).str );
	}
	return 0;
}
